home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-01-17 | 13.9 KB | 397 lines | [TEXT/KAHL] |
- /* File Library implements a reasonable interface to the more
- commonly used features of the Macintosh's Heirarchical File System.
- This library requires at least System software version 6.0, and
- supports some of the features of system 7.0.
-
- I wrote File Library to address the problems posed by working
- on a file system which uses at least four different methods to
- refer to an unopened file: volume reference number, directory
- ID, partial pathname, and full pathname. Also, the standard
- functions provided by Apple do not have a uniform calling method.
- These "PB" functions pass data via parameter blocks, the required
- fields of which can be difficult to remember, whereas prototyped
- functions guarantee that the correct number and type of arguments
- are being used. All functions, types, and constants defined by
- File Library are prefixed with the letters "File", and the first
- parameter is almost always a pointer to a FileType structure.
- Also, all functions use C format strings (except for a few glue
- functions), so you never have to worry about Pascal format strings.
-
- To use File Library, you call one of the functions with the prefix
- "FileSet", passing the initial descriptors of the file (ie, vRefNum,
- dirID, namePtr). This initializes the FileType structure. You can
- then call any of the other functions in File Library simply by
- passing a pointer to the FileType structure. You can open and close
- the file refered to by the FileType structure, and reuse the same
- FileType structure any number of times.
-
- A set of typedef's for declaring variables such as file names, volume
- reference numbers, and directory IDs are used throughout. I simply find
- it hard to remember if a directory ID is a LongInt or an Integer (it's
- a LongInt), or if a volume reference is a LongInt (it's an Integer). In
- fact, MacDTS also has problems remembering: several of their TechNotes
- use LongInts for working directory numbers while other TechNotes use
- Integers. Use of the new types eliminates this problem.
-
- Since all the references to files are concentrated in this one library,
- it will be simpler to adapt programs to use the new features soon to be
- released in System 7.0. For instance, Apple promises that there will be
- a unique 32-bit integer associated with each file, so that applications
- can always locate the file, regardless of where it is placed. Modifying
- File Library for this new feature is a trivial task, while the alternative
- of wading through hundreds of subroutines with individual declarations
- for the vRefNum, dirID, refNum, namePtr, etc. would be somewhat more
- difficult.
-
- I recently adapted File Library to use the Alias Manager of system 7.0.
- By placing a few calls to MakeFSSpec and ResolveAliasFile, I almost
- completely avoided the headache of adapting to file aliases. All my
- applications were thus immediately able to work happily with system
- 7.0. Because File Library serves as an interface between the
- application and the Macintosh file system, it is easier to adapt to
- extensions to the file system by making the modifications in only one
- place, instead of throughout the application.
-
- File Library was developed using THINK C 4.0.4, and doesn't have
- "#include" statements for any of the Macintosh managers (since
- the information is preloaded and included by THINK C). File
- Library should be portable to MPW after appropriate "#include"
- statements are added. The precompiled header I use for system
- 7.0 development contains all of the interface files distributed
- with system 7.0. I've been careful to use short integers wherever
- a 2 byte value is called for (regular integers are 2 bytes in
- THINK C and 4 bytes in MPW).
-
- Several functions check whether two files are on the same volume.
- This is done simply by comparing the 'vol' field of two file
- structures. Two files may be on the same volume yet be specified
- using two different working directories, but File Library doesn't
- normally evaluate working directories. For this reason, you should
- avoid using working directories in file structures. You can use
- FileSetWD to convert a working directory into a real volume reference
- number and directory ID, or, in system software which supports the Alias
- Manager and the MakeFSSpec routine (ie, system 7.0 or later), you may
- be able to use any of the FileSet functions [this needs to be tested].
- For instance, the function MacSysVRef returns the working directory of
- the system folder (we are not concerned with MFS volumes), so you should
- use FileSetSys if you want to access a file in the System folder.
-
- Revision History:
-
- 93/11/03
- - removed slow file structure validation operations
-
- 93/10/16
- - Decreased size of file names to 32 instead of 63. This means structres
- of type FileType can no longer be cast directly to structures of type
- FSSpec, though it does save memory. Since the maximum length of a file
- or directory name is 31, and of a volume name is 27, this should work
- ok.
- - removed FileVolNmType, FilePVolNmType
-
- 93/10/14 aih
- - eliminated some rarely used functions
-
- 93/03/25 AIH
- - Added check for FindFolder before calling it
-
- 93/03/10 AIH
- - Added a not-null check to the function used to validate a structure
- of type FileType
- - Added checks for compatability with systems prior to 7.0
-
- 91/11/16 AIH
- - Removed compatability with systems prior to 7.0
-
- 91/07/03 AIH
- - Fixed a few obscure bugs in several of the FileSet... functions
- - Clarified a few comments
-
- 91/06/06 AIH
- - Modified file for setting location of temporary files to use a prefered
- volume and directory
- - Added function to set a file's location in the extensions folder
-
- 91/05/31 AIH
- - Fixed a stupid bug which caused an infinite recursive loop when
- setting a file. I must have been asleep when I introduced the bug.
-
- 91/05/27 AIH
- - Added a few more comments and one precondition
-
- 91/05/16-17 AIH
- - Added a few comments
- - Fixed a very minor bug
- - Added function for setting a file in the system folder
-
- 91/05/09 AIH
- - Fixed a few bugs and places where errors were ignored
-
- 91/05/08 AIH
- - Fixed a few problems resolving aliases
- - Added a few comments
-
- 91/04/20-21 AIH
- - Added functions for setting temporary and preferences file locations,
- and enhanced the file setting function to use the resolve alias feature
- of system 7.0
- - Reordered internal fields of FileType structure to correspond to
- first three fields of an FSSpec structure
- - Added functions to allow use of FSSpec structures with this library
- - FileSet can return an error code if FileResolve fails
-
- 91/03/17 AIH
- - To aid the THINK C linker and to make segmentation possible
- I've split this file into several pieces.
-
- 91/03/07 AIH
- - Added functions to do range locking
- - Added lock attribute, which, when enabled, will automatically lock the
- range in a file before data are written to it. This will be expanded
- in the future to include PBRead and SetEOF operations as well.
- - When copying the data fork of a file, the file is truncated with SetEOF
- instead of deleting the destination and then creating it
-
- 91/03/02-03 AIH
- - Found TN126 which describes how to use PBCatMove
- - Changed size of FileNameType to use only 32 bytes, which is enough
- to store the longest possible file or directory name
- - A local function is used to set the a file pointer's name field,
- instead of copying into the name fields wherever the name changed
-
- 91/02/23 AIH
- - Moved function for testing if a file is already open from
- "PatchGetNextEvent.c" into this library.
-
- 91/02/06 AIH
- - The function FileUnique has been improved
-
- 91/02/05 AIH
- - Updated Finder flags
- - Added FilePathType, FilePPathType, FileVolNmType, FilePVolNmType
- - Removed FileCloseRes function since it was identical to FileClose
-
- 91/01/28 AIH
- - Added FileErase, which will overwrite an existing file with zeroes.
- This ensures that the file is completely deleted.
-
- 91/01/24 AIH
- - Added functions for getting all the finder info about files and
- folders
- - Moved archiving functions into a separate file so as to avoid
- needing the library ResourceLib which itself uses this library, resulting
- in an ugly circular reference
- - Moved header comments out of FileLib.h and into this file to avoid
- duplication of information
- - Added defines for the various finder flags
-
- 91/01/21 AIH
- - Defined FileNameType and FilePNameType.
-
- 91/01/13 AIH
- - Continuing to improve this library
-
- 90/11/14 AIH
- - Fixed indirect file references. Updated version number, added some
- string reading and writing functions.
-
- 90/11/12 Ari Halberstadt (AIH)
- - Created this library. Archiving method was original reason for
- writing it. */
-
- #include <limits.h>
- #include <string.h>
- #include <Aliases.h>
- #include <Finder.h>
- #include <Folders.h>
- #include "pstr.h"
- #include "MacLib.h"
- #include "MemoryLib.h"
- #include "StringLib.h"
- #include "FileLib.h"
-
- /*----------------------------------------------------------------------------*/
- /* validating a file structure */
- /*----------------------------------------------------------------------------*/
-
- /* true if a valid file structure */
- Boolean FileValid(FileType *fp)
- {
- if (! fp) return(false);
- if (*fp->pnm >= sizeof(FilePNameType)) return(false);
- /* The following two conditions must hold but are too slow to evaluate.
- if (strlen(fp->cnm) != *fp->pnm) return(false);
- if (memcmp(fp->cnm, fp->pnm + 1, *fp->pnm) != 0) return(false); */
- return(true);
- }
-
- /*----------------------------------------------------------------------------*/
- /* setting up a file structure */
- /*----------------------------------------------------------------------------*/
-
- /* clone the file's specification (except for the refnum) */
- void FileClone(FileType *src, FileType *dst)
- {
- require(FileValid(src));
- *dst = *src;
- dst->ref = FILE_CLOSED;
- }
-
- /* return a pointer to the name of the file */
- const char *FileName(FileType *fp)
- {
- require(FileValid(fp));
- return(fp->cnm);
- }
-
- /* set the file's name; you may want to call FileResolve after calling
- this function */
- void FileNameSet(FileType *fp, const FileNameType name)
- {
- require(StrValid(name, sizeof(FileNameType)));
- strcpy(fp->cnm, name);
- c2pstrcpy(fp->pnm, name);
- }
-
- /* convert the file structure to an FSSpec */
- void FileToFSSpec(FileType *fp, FSSpec *spec)
- {
- OSErr err = noErr;
-
- require(FileValid(fp));
- require(MacHasFSSpec());
- err = FSMakeFSSpec(fp->vol, fp->dir, fp->pnm, spec);
- if (err == fnfErr)
- err = noErr;
- FailOSErr(err);
- }
-
- /* Resolve the file's alias, or do nothing if the Alias Manager is unavailable.
- This function is always called after any of the file setting functions
- are called, so there is usually no need for your application to call this
- function directly. (Hooray for data hiding!) */
- void FileResolve(FileType *fp)
- {
- FSSpec spec;
- Boolean folder;
- Boolean aliased;
- OSErr err;
-
- if (MacHasAliases()) {
- FileToFSSpec(fp, &spec);
- err = ResolveAliasFile(&spec, true, &folder, &aliased);
- if (err == fnfErr)
- err = noErr;
- FailOSErr(err);
- fp->vol = spec.vRefNum;
- fp->dir = spec.parID;
- FileNameSet(fp, p2cstr(spec.name));
- }
- }
-
- /* set the file's identifier */
- void FileSet(FileType *fp, FileVolType vol, FileDirType dir,
- const FileNameType name)
- {
- require(name != fp->cnm); /* this is to avoid a possible (stupid) bug */
- memclr(fp, sizeof(FileType));
- fp->vol = vol;
- fp->dir = dir;
- FileNameSet(fp, name);
- FileResolve(fp);
- ensure(FileValid(fp));
- }
-
- /* This function is equivalent to FileSet, except that it takes
- a working directory ID instead of a volume reference number
- and a directory ID. This function is most useful when accessing
- a file selected using the Standard File package. */
- void FileSetWD(FileType *fp, FileWDirType wdref, const FileNameType name)
- {
- FileVolType vol;
- FileDirType dir;
- long procid;
-
- FailOSErr(GetWDInfo(wdref, &vol, &dir, &procid));
- FileSet(fp, vol, dir, name);
- }
-
- /* this is the same as FileSet, except it takes the reference number of an
- open file */
- void FileSetRef(FileType *fp, FileRefType ref)
- {
- FCBPBRec pb;
- FileNameType name;
-
- *name = 0;
- memclr(&pb, sizeof(FCBPBRec));
- pb.ioNamePtr = (StringPtr) name;
- pb.ioRefNum = ref;
- FailOSErr(PBGetFCBInfo(&pb, false));
- FileSet(fp, pb.ioFCBVRefNum, pb.ioFCBParID, p2cstr((StringPtr) name));
- }
-
- /* this is identical to FileSet except the file's specification is taken
- from an FSSpec structure */
- void FileSetFSSpec(FileType *fp, const FSSpec *spec)
- {
- FileNameType name;
- FileSet(fp, spec->vRefNum, spec->parID, p2cstrcpy(name, spec->name));
- }
-
- /* This is similar to FileSet, except that it takes only the name of a
- file, and sets the file's location to the system folder. */
- void FileSetSys(FileType *fp, const FileNameType name)
- {
- FileVolType vol = MacSysVRef();
- FileDirType dir = 0;
-
- if (MacHasFindFolder()) {
- FailOSErr(FindFolder(kOnSystemDisk, kSystemFolderType,
- kDontCreateFolder, &vol, &dir));
- }
- FileSet(fp, vol, dir, name);
- }
-
- /* This is similar to FileSet, it places the file in the
- temporary items folder on the specified volume. The FileUnique
- function is then called to ensure that the file's name is
- unique in that directory. */
- void FileSetTemp(FileType *fp)
- {
- require(FileValid(fp));
- if (MacHasFindFolder()) {
- FailOSErr(FindFolder(fp->vol, kTemporaryFolderType, kCreateFolder,
- &fp->vol, &fp->dir));
- }
- FileUnique(fp);
- }
-
- /* This is similar to FileSet, except it takes only the name of a file and
- sets the file in the preferences folder. */
- void FileSetPref(FileType *fp, const FileNameType name)
- {
- FileVolType vol = MacSysVRef();
- FileDirType dir = 0;
-
- if (MacHasFindFolder()) {
- FailOSErr(FindFolder(kOnSystemDisk, kPreferencesFolderType,
- kCreateFolder, &vol, &dir));
- }
- FileSet(fp, vol, dir, name);
- }
-
- /* This is similar to FileSet, except it takes only the name of a file, and
- sets the file in the extensions folder. */
- void FileSetExtension(FileType *fp, const FileNameType name)
- {
- FileVolType vol = MacSysVRef();
- FileDirType dir = 0;
-
- if (MacHasFindFolder()) {
- FailOSErr(FindFolder(kOnSystemDisk, kExtensionFolderType,
- kCreateFolder, &vol, &dir));
- }
- FileSet(fp, vol, dir, name);
- }
-